using System;
using System.Collections;
using UnityEngine;

namespace EventBehaviorTree
{
    [Serializable]
    public class TimerSequencer : Container//todo: is condition node?
    {
        private int _duration;
        private int _remainFrame;
        private IEnumerator _timer;
        private TimerPattern _pattern;
        public int Duration { get => _duration; set => _duration = Mathf.Max(0, value); }
        public int RemainFrame { get => _remainFrame; set => _remainFrame = Mathf.Max(0, value); }
        public TimerSequencer(string pattern, string duration)
        {
            Duration = int.Parse(duration);
            _pattern = (TimerPattern)Enum.Parse(typeof(TimerPattern), pattern);
        }
        public override void Initialize(MonoBehaviour behaviorTree)
        {
            base.Initialize(behaviorTree);
            _timer = null;
        }
        private IEnumerator Timer()
        {
            RemainFrame = Duration;
            switch (_pattern)
            {
                case TimerPattern.While:
                    while (RemainFrame > 0)
                    {
                        RemainFrame--;
                        yield return new WaitForSeconds(0);//todo: time interval
                        SubNodeCheck();
                    }
                    break;
                case TimerPattern.Until:
                    while (RemainFrame > 0)
                    {
                        RemainFrame--;
                        yield return new WaitForSeconds(0);
                    }
                    SubNodeCheck();
                    break;
                default:
                    break;
            }
            Reset();
            CompositeNodeEvent(NodeMessage.Success);//time has run out
        }
        public override void NodeEvent(NodeMessage nodeMessage)
        {
            switch (nodeMessage)
            {
                case NodeMessage.Start:
                    if (_timer == null)//start a timer
                    {
                        Reset();
                        _timer = Timer();
                        _monoBehavior.StartCoroutine(_timer);
                    }
                    else
                    {
                        _stepCounter = 0;//todo: when counter with a task spending multiple frame
                        _subNodes[_stepCounter].NodeEvent(NodeMessage.Start);//first task of timer
                    }
                    return;
                case NodeMessage.Success:
                    _stepCounter++;
                    if (_stepCounter < _subNodes.Count)
                    {
                        _subNodes[_stepCounter].NodeEvent(NodeMessage.Start);
                        return;
                    }
                    return;//success of subNodes do not represent the success of node, so return and wait for restart
                case NodeMessage.COMMAND_Stop:
                    Reset();
                    foreach (EventNode subNode in _subNodes) { subNode.NodeEvent(NodeMessage.COMMAND_Stop); }
                    return;
                default:
                    break;
            }
            Reset();
            CompositeNodeEvent(nodeMessage);
        }
        public override void Reset()
        {
            base.Reset();
            if (_timer != null)
            {
                _monoBehavior.StopCoroutine(_timer);
                _timer = null;
            }
        }
    }
}
